package top.zhangjianyong.tools.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import top.zhangjianyong.tools.entity.Vegetable;

import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author ： zhangjianyong
 * @date ： 2022/9/22 2:02 PM
 */
@Slf4j
public class CanteenApiUtil {


    private final static String HYSY_PREFIX_URL = "http://hysy.yksmart2.com";
    private final static String PREFIX_URL = "http://jjwz.yksmart3.com:8281";
    private final static String WX_ID = "oPO0Kw84tLz13_97fWcSgABSP47k";

    private final static ThreadLocal<String> DES_KEY = new ThreadLocal<>();


    public final static ThreadLocal<StringBuilder> LOG_MESSAGE = new ThreadLocal<>();

    private final static DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void resetMessage() {
        LOG_MESSAGE.set(null);
    }

    public static String getMessage() {
        StringBuilder sb = LOG_MESSAGE.get();
        if (sb == null) return "";
        return sb.toString();
    }

    public static void addMessage(String message) {
        StringBuilder sb = LOG_MESSAGE.get();
        if (sb == null) {
            sb = new StringBuilder();
            LOG_MESSAGE.set(sb);
        }

        sb.append(message).append(" ")
                .append("< ").append(DTF.format(LocalDateTime.now())).append(" >")
                .append("\n<br>\n");
    }

    public static void addMessage(String message, Object... obj) {
        for (Object s : obj) {
            if (s == null) s = "null";
            message = message.replaceFirst("\\{}", s.toString());
        }
        addMessage(message);
    }

    public static void addMessage(boolean logFlag, String message, Object... obj) {
        if (logFlag) {
            log.info(message, obj);
        }
        addMessage(message, obj);
    }


    /**
     * http://jjwz.yksmart3.com:8281/cateringweb/weixin/getWxLoginPage.action
     * http://hysy.yksmart2.com/service/route/login
     * 获取登陆地址
     *
     * @return
     */
    public static String loginUrl() {

        String url = HYSY_PREFIX_URL + "/service/route/login?grpid=5761000007&code=" + UUIDUtil.uuid() + "&state=STATE";
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        String loginUrl = execute.header("Location");
        addMessage(true, "[登陆地址] {}", loginUrl);
        return loginUrl;
    }

    /**
     * 获取登陆密钥
     *
     * @param url
     * @return
     */
    public static String loginKey(String url) {
        addMessage(true, "[进入登陆页面] 请求地址：{}", url);
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        String html = execute.body();
        // 创建 Pattern 对象
        Pattern r = Pattern.compile("'([\\w|\\d]{32})'");
        // 现在创建 matcher 对象
        Matcher m = r.matcher(html);
        m.find();
        String key = m.group(1);
        DES_KEY.set(key);
        addMessage(true, "[获取DES密钥] {}", key);
        return key;
    }

    /**
     * 登陆
     *
     * @param username
     * @param password
     * @return
     */
    public static String login(String username, String password) {
        addMessage(true, "[密码加密] 密码：{} 密钥：{}", password, DES_KEY.get());
        String pswd = DesUtil.encrypt(password, DES_KEY.get());
        addMessage(true, "[密码加密] 密文：{}", pswd);
        String url = PREFIX_URL + "/cateringweb/weixin/loginWxCatering.action";
        addMessage(true, "[登陆接口] 请求地址：{}", url);
        HttpRequest post = HttpUtil.createPost(url);
        post.form("idcard", username);
        post.form("psw", pswd);
        post.form("wxid", WX_ID);
        post.form("serivceo", "oPO0Kw84tLz13_97fWcSgABSP47k");
        post.contentType("application/x-www-form-urlencoded");

        HttpResponse execute = post.execute();
        String location = execute.header("Location");
        addMessage(true, "[登陆接口] 跳转地址：{}", location);
        return location;
    }

    /**
     * 进入首页
     *
     * @param uri
     */
    public static void getInfoPage(String uri) {
        String url = uri;
        if (!uri.startsWith("http")) {
            url = PREFIX_URL + uri;
        }
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        log.info("[登陆重定向] 跳转页面:{}", uri);
        addMessage("[登陆重定向] 跳转页面:{}", uri);
    }

    /**
     * 获取菜单链接
     *
     * @return
     */
    public static List<String> getMenuUris() {
        List<String> menuUris = getMenuUris2();
        menuUris.addAll(getMenuUris3());
        return menuUris;
    }

    /**
     * 获取午餐的菜单链接
     *
     * @return
     */
    public static List<String> getMenuUris2() {
        // /cateringweb/weixin/getPage_getShopRq.action?datecs=2022-12-26&cc=2&bizid=11012&floor=0
        String url = PREFIX_URL + "/cateringweb/weixin/getPage_getShopPage.action";
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        String body = execute.body();

        List<String> list = new ArrayList<>();
        // 创建 Pattern 对象
        Pattern r = Pattern.compile("'(getPage_getShopRq\\.action\\?datecs=[\\w]{4}-[\\w]{2}-[\\w]{2}&cc=2&bizid=[\\w]{5}&floor=.?)'");
        // 现在创建 matcher 对象
        Matcher m = r.matcher(body);

        //午餐
        while (m.find()) {
            String group = m.group(1);
            list.add(group);
        }

        list.forEach(uri -> {
            log.info("[菜单链接] {}", uri);
            addMessage("[菜单链接] {}", uri);
        });

        return list;
    }

    /**
     * 获取晚餐的菜单链接
     *
     * @return
     */
    public static List<String> getMenuUris3() {
        // /cateringweb/weixin/getPage_getShopRq.action?datecs=2022-12-26&cc=2&bizid=11012&floor=0
        String url = PREFIX_URL + "/cateringweb/weixin/getPage_getShopPage.action";
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        String body = execute.body();
        //获取晚餐链接
        String ccUrl = RegexUtil.matcherFirst(body,
                "'(getPage_getShopCc\\.action\\?datecs=[\\w]{4}-[\\w]{2}-[\\w]{2}&cc=3&bizid=[\\w]{5}&floor=.?)'",
                1);

        if (ccUrl == null) {
            throw new RuntimeException("未获取到晚餐链接");
        }
        if (!ccUrl.startsWith("http")) {
            ccUrl = PREFIX_URL + "/cateringweb/weixin/" + ccUrl;
        }

        get = HttpUtil.createGet(ccUrl);
        execute = get.execute();
        body = execute.body();
        List<String> list = RegexUtil.matcher(body,
                "'(getPage_getShopRq\\.action\\?datecs=[\\w]{4}-[\\w]{2}-[\\w]{2}&cc=3&bizid=[\\w]{5}&floor=.?)'",
                1);
        return list;
    }

    /**
     * http://jjwz.yksmart3.com:8281/cateringweb/weixin/getPage_getShopRq.action?datecs=2022-09-27&cc=&bizid=11001
     * 进入点餐页面
     */
    public static List<Vegetable> getMenu(String uri, Map<String, String> map, boolean message) {
        String datecs = map.get("datecs");
        String cc = map.get("cc");
        String ccStr = cc.equals("1") ? "早餐" : cc.equals("3") ? "晚餐" : "午餐";
        addMessage(message, "[获取菜单] {} {}", datecs, ccStr);
        String url = PREFIX_URL + "/cateringweb/weixin/" + uri;
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        String body = execute.body();
        List<Vegetable> menu = CanteenHtmlUtil.getMenu(body, datecs, cc);
        menu.forEach(vegetable -> {
                    log.info("[获取菜单] {} {}-{} 库存:{}",
                            vegetable.getNo(),
                            vegetable.getName(),
                            vegetable.getDescription(),
                            vegetable.getStock());
                    addMessage("[获取菜单] {} {}-{} 库存:{}",
                            vegetable.getNo(),
                            vegetable.getName(),
                            vegetable.getDescription(),
                            vegetable.getStock());
                }
        );
        return menu;
    }

    /**
     * http://jjwz.yksmart3.com:8281/cateringweb/weixin/getPage_getShopRq.action?datecs=2022-09-27&cc=&bizid=11001
     * 进入点餐页面
     */
    public static List<Vegetable> getMenu(String uri, boolean message) {
        Map<String, String> map = StringUtil.uriToMap(uri);
        return getMenu(uri, map, message);
    }

    /**
     * http://jjwz.yksmart3.com:8281/cateringweb/weixin/getPage_getShopRq.action?datecs=2022-09-27&cc=&bizid=11001
     * 进入点餐页面
     */
    public static List<Vegetable> getMenu(String datecs, String cc, boolean message) {
        return getMenu("getPage_getShopRq.action?datecs="
                + datecs + "&cc=" + cc
                + "&bizid=11001", message);
    }

    /**
     * http://jjwz.yksmart3.com:8281/cateringweb/weixin/jrgwc4wx.action?setmno=007622&ydsl=1&orgid=01&suborgid=000&bizid=11001&cc=&datecs=2022-09-28
     * 点餐
     *
     * @param vegetable
     */
    public static Boolean addOrder(Vegetable vegetable) {
        String url = PREFIX_URL + "/cateringweb/weixin/jrgwc4wx.action?setmno="
                + vegetable.getNo() + "&ydsl=1&orgid=01&suborgid=000&bizid=" + vegetable.getBizid()
                + "&datecs=" + vegetable.getDatecs() + "&cc=" + vegetable.getCc();
        HttpRequest post = HttpUtil.createPost(url);
        HttpResponse execute = post.execute();
        String body = execute.body();
        Boolean flag = JSON.parseObject(body).getBoolean("flag");
        log.info("[点餐] {}-{}:{}", vegetable.getName(), vegetable.getDescription(), flag);
        addMessage("[点餐] {}:{}", vegetable.getName(), flag);

        return flag;
    }

    /**
     * http://jjwz.yksmart3.com:8281/cateringweb/weixin/getPage_getCartPage.action
     * 进入购物车
     */
    public static Integer getCarPage() {
        String url = PREFIX_URL + "/cateringweb/weixin/getPage_getCartPage.action";
        HttpRequest get = HttpUtil.createGet(url);
        String body = get.execute().body();
        List<Vegetable> car = CanteenHtmlUtil.getCar(body);
        if (CollectionUtil.isNotEmpty(car)) {
            car.forEach(vegetable -> {
                addMessage(true, "[购物车] {} {} : {}", vegetable.getDatecs(),
                        vegetable.getName(), vegetable.getDescription());
            });
            return car.size();
        } else {
            addMessage(true, "[购物车] 购物车为空");
            return 0;
        }


    }

    /**
     * http://jjwz.yksmart3.com:8281/cateringweb/weixin/cartPage4DirectPay.action
     * 进入下单页面
     */
    public static void goSaveOrder() {
        String url = PREFIX_URL + "/cateringweb/weixin/getPage_getSettlementPage.action?toDinnerRpt=1&tmporder=0000000000000000";
        HttpRequest get = HttpUtil.createGet(url);
        HttpResponse execute = get.execute();
        String body = execute.body();
        String amt = CanteenHtmlUtil.getAmt(body);
        addMessage("[提交订单] 订单金额: {}", amt);
    }

    /**
     * http://jjwz.yksmart3.com:8281/cateringweb/weixin/tjdj4wx.action?orgid=01&address=&payway=7
     * 下单
     */
    public static Boolean saveOrder() {
        String url = PREFIX_URL + "/cateringweb/weixin/tjdj4wx.action?orgid=01&address=&payway=7";
        HttpRequest post = HttpUtil.createPost(url);
        post.header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        HttpResponse execute = post.execute();
        String body = execute.body();
        JSONObject json = JSON.parseObject(body);
        Boolean flag = json.getBoolean("flag");
        String ccnum = json.getString("ccnum");
        log.info("[提交订单] 结果: {} 已点餐数: {}", flag, ccnum);
        addMessage("[提交订单] 结果: {} 已点餐数: {}", flag, ccnum);
        if (!flag)
            return saveOrder();
        return flag;
    }

    public static void test() {
        //获取获取登陆地址
        String logUrl = loginUrl();
        //获取des密钥
        loginKey(logUrl);
        //登陆
        String uri = login("20211107", "520520");
        //重定向首页
        getInfoPage(uri);
        //获取可点日期
        List<String> menuUri = getMenuUris();

        for (String mUri : menuUri) {
            //获取菜单信息
            List<Vegetable> menu = getMenu(mUri, true);
            Vegetable vegetable = menu.stream().filter(m -> m.getName().contains("套餐E"))
                    .findAny()
                    .orElseGet(() -> {
                        log.info("[获取套餐] 未找到套餐");
                        return null;
                    });
            if (vegetable != null /*&& vegetable.getStock() > 0*/) {
                //点餐
                addOrder(vegetable);
                //进入购物车
                getCarPage();
                //获取订单信息
                goSaveOrder();
                //提交订单
                saveOrder();
            } else {
                log.info("[检查库存] 该套餐没有库存");
            }
        }
    }

    /**
     * 通用的前置处理
     *
     * @param userName
     * @param password
     */
    public static void loginForCanteen(String userName, String password) {
        //获取sessionId
        String loginUrl = CanteenApiUtil.loginUrl();
        //获取des密钥
        CanteenApiUtil.loginKey(loginUrl);
        //登陆
        String indexUri = CanteenApiUtil.login(userName, password);
        //重定向首页
        CanteenApiUtil.getInfoPage(indexUri);
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        loginForCanteen("20211107", "520520");

        List<String> menuUris3 = getMenuUris3();
        System.out.println(JSONObject.toJSONString(menuUris3));
    }


}
